package com.peter.proxy.hkgolden.api;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.peter.framework.service.memcache.CacheService;
import com.peter.framework.service.urlfetch.HttpService;

@Singleton
public class ContentServiceImpl implements ContentService {

	private ObjectMapper mapper = new ObjectMapper();

	private HttpService httpService;

	private CacheService cacheService;

	protected final Logger logger = LoggerFactory.getLogger(getClass());

	@Inject
	public ContentServiceImpl(HttpService httpService, CacheService cacheService) {
		this.httpService = httpService;
		this.cacheService = cacheService;
		final URL url = ContentServiceImpl.class.getResource("channels.xml");
		final SAXReader saxReader = new SAXReader();
		try {
			final Document document = saxReader.read(url);
			final Element select = document.getRootElement();
			final List<Element> optionList = select.elements();
			for (Element option : optionList) {
				// logger.debug("option.value = {}", option.attribute("value")
				// .getValue());
				// logger.debug("option.text = {}", option.getTextTrim());
				channelMap.put(option.attribute("value").getValue(), option
						.getTextTrim());
			}
		} catch (DocumentException e) {
		}
	}

	final LinkedHashMap<String, String> channelMap = new LinkedHashMap<String, String>();

	@Override
	public Map<String, String> channels() {
		return channelMap;
	}

	@Override
	public Collection<Topic> topics(URL url) throws IOException {
		final String jsonData = httpService.getFromUrl(url);
		if (jsonData == null) {
			return null;
		}
		final JsonNode rootNode = mapper.readValue(jsonData, JsonNode.class);
		return mapper.readValue(rootNode.get("topic_list").traverse(),
				new TypeReference<ArrayList<Topic>>() {
				});
	}

	@Override
	public Collection<Topic> topics(String type, int page) throws IOException {
		final URL url = new URL("http://api.hkgolden.com/topics.aspx"
				+ "?returntype=json" + "&page=" + page + "&pagesize=30"
				+ "&type=" + type);
		logger.debug("cache.key = {}", url.getPath() + url.getQuery());
		Collection<Topic> topics = (Collection<Topic>) cacheService.get(url
				.getPath()
				+ url.getQuery());
		if (topics != null) {
			return topics;
		}
		topics = topics(url);
		cacheService.put(url.getPath() + url.getQuery(), topics);
		return topics;
	}

	@Override
	public Topic messages(URL url) throws IOException {
		final String jsonData = httpService.getFromUrl(url);
		if (jsonData == null) {
			return null;
		}
		return mapper.readValue(jsonData, new TypeReference<Topic>() {
		});
	}

	@Override
	public Topic messages(int messageId, int page) throws IOException {
		int end = page * 50;
		int start = end - 49;
		final URL url = new URL("http://api.hkgolden.com/view.aspx"
				+ "?returntype=json" + "&message=" + messageId + "&start="
				+ start + "&end=" + end);
		logger.debug("cache.key = {}", url.getPath() + url.getQuery());
		Topic topic = (Topic) cacheService.get(url.getPath() + url.getQuery());
		if (topic != null) {
			return topic;
		}
		topic = messages(url);
		cacheService.put(url.getPath() + url.getQuery(), topic);
		return topic;
	}

}
